package com.dusk.tool
{
    import com.adobe.crypto.Adler32;
    import com.dusk.game.Logger;
    
    import flash.utils.ByteArray;
    import flash.utils.Proxy;
    import flash.utils.flash_proxy;
    
    public dynamic class DataBase extends Proxy
    {
        public function DataBase()
        {
            super();
            _data = {};
            _code = {};
        }
        
        private var _defaultValue:* = undefined;
        private var _data:Object;
        private var _code:Object;
        
        public function setDefaultValue(value:*):void
        {
            _defaultValue = value;
        }
        
        public function deleteAllValue():void
        {
            for (var key:String in _data)
            {
                delete _data[key];
                delete _code[key];
            }
        }
        
        public function clearData():void
        {
            var key:String;
            for (key in _data)
            {
                delete _data[key];
            }
            for (key in _code)
            {
                delete _code[key];
            }
        }
        
        override flash_proxy function callProperty(name:*, ...rest):*
        {
            var func:Function = _data[name] as Function;
            if (!func)
            {
                throw new Error("未找到方法: " + name);
            }
            return func.apply(null, rest);
        }
        
        override flash_proxy function getProperty(name:*):*
        {
            if (name == null || name == undefined)
            {
                return null;
            }
            if (!_code.hasOwnProperty(name) || !_data.hasOwnProperty(name))
            {
                flash_proxy::setProperty(name, _defaultValue);
//                Logger.log("创建默认值数据: " + name);
            }
            var value:* = _data[name];
            
            dataCheck:
            {
                var ba:ByteArray = new ByteArray();
                if (value == null || value == undefined)
                {
                    ba.writeByte(0xFF);
                }
                else if (value is int)
                {
                    ba.writeInt(value);
                }
                else if (value is Number)
                {
                    ba.writeDouble(value);
                }
                else if (value is Boolean)
                {
                    ba.writeBoolean(value);
                }
                else if (value is String)
                {
                    ba.writeUTFBytes(value);
                }
                else
                {
                    ba.writeObject(value);
                }
                if (ba.length && _code[name] == Adler32.hash(ba))
                {
                    /*Logger.log("读取值：" + name);
                    Logger.log("Adler：" + _code[name]);*/
                    return value
                }
                else
                {
                    throw new Error("检测到非法修改: " + name);
                }
            }
        }
        
        override flash_proxy function hasProperty(name:*):Boolean
        {
            return _code.hasOwnProperty(name);
        }
        
        override flash_proxy function setProperty(name:*, value:*):void
        {
            var ba:ByteArray = new ByteArray();
            if (value == null || value == undefined)
            {
                ba.writeByte(0xFF);
            }
            else if (value is int)
            {
                ba.writeInt(value);
            }
            else if (value is Number)
            {
                ba.writeDouble(value);
            }
            else if (value is Boolean)
            {
                ba.writeBoolean(value);
            }
            else if (value is String)
            {
                ba.writeUTFBytes(value);
            }
            else
            {
                ba.writeObject(value);
            }
            if (ba.length)
            {
                _data[name] = value;
                _code[name] = Adler32.hash(ba);
            }
        }
        
        public function dispose():void
        {
            var key:String;
            for (key in _data)
            {
                _data[key] = undefined;
            }
            for (key in _code)
            {
                _code[key] = undefined;
            }
            _data = {};
            _code = {};
        }
    }
}
